package qy.qyalgotrader.utils;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.zeroc.Ice.Communicator;
import com.zeroc.Ice.ObjectPrx;
import com.zeroc.Ice.Util;

import qy.jalgotrade.Initializer;

/**
 * <pre>
 * common services:
 * 
 * *MongoDb service
 * 
 * *Ice Wapi service
 * 
 * *Ice Tushare service
 * 
 * *Ice Tts service
 * 
 * *Ice View service
 * </pre>
 * 
 * @author c-geo
 *
 */
public final class Services {

	private Logger logger = LoggerFactory.getLogger(Services.class);

	private static Services instance;

	/**
	 * 
	 */
	private MongoClient mongoClient;

	/**
	 * 
	 */
	private Communicator communicator;

	private String __iceWapiProxyStringTpl;

	private List<String> __iceWapiProxies;

	private String __iceTushareProxyStringTpl;

	private List<String> __iceTushareProxies;

	private String __iceTtsProxyStringTpl;

	private List<String> __iceTtsServiceProxies;

	private String __iceViewProxyStringTpl;

	private List<String> __iceViewProxies;

	public static Services getInstance() {

		synchronized (Services.class) {

			if (instance == null) {
				instance = new Services();
			}
			return instance;
		}
	}

	/**
	 * 
	 */
	@SuppressWarnings("unused")
	private Services() {

		/*
		 * init mongodb:
		 */
		String mongodbHost = Initializer.APP_DEPLOY_CONFIG.getSection("mongodb").getString("host");
		String mongodbport = Initializer.APP_DEPLOY_CONFIG.getSection("mongodb").getString("port");
		String mongodbUsername = Initializer.APP_DEPLOY_CONFIG.getSection("mongodb").getString("port");
		String mongodbPasswrod = Initializer.APP_DEPLOY_CONFIG.getSection("mongodb").getString("port");
		String mongodbCs = String.format("mongodb://%s:%s", mongodbHost, mongodbport);
		mongoClient = MongoClients.create(mongodbCs);
		// init ice:
		communicator = Util.initialize();
		/*
		 * init ice_wapi:
		 */
		String iceWapiHost = Initializer.APP_DEPLOY_CONFIG.getSection("ice_wapi").getString("host");
		String iceWapiPort = Initializer.APP_DEPLOY_CONFIG.getSection("ice_wapi").getString("port");
		__iceWapiProxyStringTpl = String.format("%%s:tcp -h %s -p %s", iceWapiHost, iceWapiPort);
		__iceWapiProxies = new ArrayList<>();
		for (String proxy : Initializer.APP_DEPLOY_CONFIG.getSection("ice_wapi").getString("proxiesList").split(",")) {
			// 检查 proxiesList 中, 所有 proxy 都 可达到:
			try {
				ObjectPrx o = communicator.stringToProxy(String.format(__iceWapiProxyStringTpl, proxy.trim()));
				o.ice_ping();
				__iceWapiProxies.add(proxy.trim());
			} catch (Exception e) {
				logger.error("Init ice_wapi faild: {}", ExceptionUtils.getStackTrace(e));
			}
		}
		/*
		 * init ice_tushare:
		 */
		String iceTsHost = Initializer.APP_DEPLOY_CONFIG.getSection("ice_tushare").getString("host");
		String iceTsPort = Initializer.APP_DEPLOY_CONFIG.getSection("ice_tushare").getString("port");
		__iceTushareProxyStringTpl = String.format("%%s:tcp -h %s -p %s", iceTsHost, iceTsPort);
		__iceTushareProxies = new ArrayList<>();
		for (String proxy : Initializer.APP_DEPLOY_CONFIG.getSection("ice_tushare").getString("proxiesList").split(",")) {
			// 检查 proxiesList 中, 所有 proxy 都 可达到:
			try {
				ObjectPrx o = communicator.stringToProxy(String.format(__iceTushareProxyStringTpl, proxy.trim()));
				o.ice_ping();
				__iceTushareProxies.add(proxy.trim());
			} catch (Exception e) {
				logger.error("Init ice_tushare faild: {}", ExceptionUtils.getStackTrace(e));
			}
		}
		/*
		 * init ice_tts:
		 */
		String iceTtsHost = Initializer.APP_DEPLOY_CONFIG.getSection("ice_tts").getString("host");
		String iceTtsPort = Initializer.APP_DEPLOY_CONFIG.getSection("ice_tts").getString("port");
		__iceTtsProxyStringTpl = String.format("%%s:tcp -h %s -p %s", iceTtsHost, iceTtsPort);
		__iceTtsServiceProxies = new ArrayList<>();
		for (String proxy : Initializer.APP_DEPLOY_CONFIG.getSection("ice_tts").getString("proxiesList").split(",")) {
			// 检查 proxiesList 中, 所有 proxy 都 可达到:
			try {
				ObjectPrx o = communicator.stringToProxy(String.format(__iceTtsProxyStringTpl, proxy.trim()));
				o.ice_ping();
				__iceTtsServiceProxies.add(proxy.trim());
			} catch (Exception e) {
				logger.error("Init ice_tts faild: {}", ExceptionUtils.getStackTrace(e));
			}
		}
		/*
		 * init ice_view:
		 */
		String iceViewHost = Initializer.APP_DEPLOY_CONFIG.getSection("ice_view").getString("host");
		String iceViewPort = Initializer.APP_DEPLOY_CONFIG.getSection("ice_view").getString("port");
		__iceViewProxyStringTpl = String.format("%%s:tcp -h %s -p %s", iceViewHost, iceViewPort);
		__iceViewProxies = new ArrayList<>();
		for (String proxy : Initializer.APP_DEPLOY_CONFIG.getSection("ice_view").getString("proxiesList").split(",")) {
			// 检查 proxiesList 中, 所有 proxy 都 可达到:
			try {
				ObjectPrx o = communicator.stringToProxy(String.format(__iceViewProxyStringTpl, proxy.trim()));
				o.ice_ping();
				__iceViewProxies.add(proxy.trim());
			} catch (Exception e) {
				logger.error("Init ice_view faild: {}", ExceptionUtils.getStackTrace(e));
			}
		}
	}

	/*
	 * 
	 */
	@Override
	protected void finalize() throws Throwable {

		if (mongoClient != null) {
			mongoClient.close();
		}
		if (communicator != null) {
			communicator.destroy();
		}
	}

	/**
	 * 
	 */
	public void stop() {

		communicator.destroy();
		mongoClient.close();
	}

	/**
	 * 
	 * @return
	 */
	public MongoClient getMongoClient() {

		return mongoClient;
	}

	/**
	 * 
	 * @return
	 */
	public Communicator getCommunicator() {

		return communicator;
	}

	/**
	 * 
	 * @param id
	 * @return
	 */
	public ObjectPrx createIceWapiProxy(String id) {

		ObjectPrx obj = communicator.stringToProxy(String.format(__iceWapiProxyStringTpl, id));
		return obj;
	}

	/**
	 * 
	 * @param id
	 * @return
	 */
	public ObjectPrx createIceTushareProxy(String id) {

		ObjectPrx obj = communicator.stringToProxy(String.format(__iceTushareProxyStringTpl, id));
		return obj;
	}

	/**
	 * 
	 * @param id
	 * @return
	 */
	public ObjectPrx createIceTtsServiceProxy(String id) {

		ObjectPrx obj = communicator.stringToProxy(String.format(__iceTtsProxyStringTpl, id));
		return obj;
	}

	/**
	 * 
	 * @param id
	 * @return
	 */
	public ObjectPrx createIceViewProxy(String id) {

		ObjectPrx obj = communicator.stringToProxy(String.format(__iceViewProxyStringTpl, id));
		return obj;
	}
}
